package com.tanhua.manager.service;

import cn.hutool.core.date.DateField;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanhua.manager.domain.AnalysisByDay;
import com.tanhua.manager.domain.Log;
import com.tanhua.manager.mapper.AnalysisByDayMapper;
import com.tanhua.manager.mapper.LogMapper;
import com.tanhua.manager.utils.ComputeUtil;
import com.tanhua.manager.vo.AnalysisSummaryVo;
import com.tanhua.manager.vo.AnalysisUsersVo;
import com.tanhua.manager.vo.DataPointVo;
import net.sf.jsqlparser.statement.select.Distinct;
import org.checkerframework.checker.units.qual.A;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveFindOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class AnalysisByDayService {

    @Autowired
    private LogMapper logMapper;

    @Autowired
    private AnalysisByDayMapper analysisByDayMapper;

    public void analysis() {
        AnalysisByDay analysisByDay = new AnalysisByDay();
        String todayStr = new DateTime().toString("yyyy-MM-dd");
//        1、record_date 记录时间
        analysisByDay.setRecordDate(new org.joda.time.DateTime(todayStr).toDate()); //要求格式是yyyy-MM-dd的一个日期型
//        2、num_registered 有多少人注册
        Integer numRegistered = logMapper.queryNumRegisteredOrLogin(todayStr, "0102");
        analysisByDay.setNumRegistered(numRegistered);
//        3、num_login 有多少人登录
        Integer numLogin = logMapper.queryNumRegisteredOrLogin(todayStr, "0101");
        analysisByDay.setNumLogin(numLogin);
//        4、num_active 有多少人活跃
        Integer numActive = logMapper.queryNumActive(todayStr);
        analysisByDay.setNumActive(numActive);
//        5、num_retention1d 当前有多少留存人数 前一天注册后，今天依然在app上活跃
        String yesTodayStr = new org.joda.time.DateTime(todayStr).minusDays(1).toString("yyyy-MM-dd");
        Integer numRetention1d = logMapper.queryNumRetention1d(todayStr, yesTodayStr);
        analysisByDay.setNumRetention1d(numRetention1d);
        analysisByDayMapper.insert(analysisByDay);
    }

    public ResponseEntity summary() {
        AnalysisSummaryVo analysisSummaryVo = new AnalysisSummaryVo();
//        1、累计用户 有多少人注册过 select sum(num_registered)  from tb_analysis_by_day
        Long cumulativeUsers = analysisByDayMapper.queryCumulativeUsers();
        analysisSummaryVo.setCumulativeUsers(cumulativeUsers);
        String todayStr = new DateTime().toString("yyyy-MM-dd");
        String before30Day = new org.joda.time.DateTime().minusDays(30).toString("yyyy-MM-dd");
        String before7Day = new org.joda.time.DateTime().minusDays(7).toString("yyyy-MM-dd");
        String before1Day = new org.joda.time.DateTime().minusDays(1).toString("yyyy-MM-dd");
//        2、过去30天活跃用户  2021-01-19  ---2020-12-19  select sum(num_active)  from tb_analysis_by_day where record_date<='2021-01-19' and  record_date>='2020-12-19'
        Long activePassMonth = analysisByDayMapper.queryActivePass(todayStr, before30Day);
        analysisSummaryVo.setActivePassMonth(activePassMonth);
//        3、过去7天活跃用户   2021-01-19  ---2021-01-12  select sum(num_active)  from tb_analysis_by_day where record_date<='2021-01-19' and  record_date>='2021-01-12'
        Long activePassWeek = analysisByDayMapper.queryActivePass(todayStr, before7Day);
        analysisSummaryVo.setActivePassWeek(activePassWeek);

//        4、今日新增用户  select  count(DISTINCT user_id)  from tb_log  where log_time= '2021-01-19' and type='0102'
        Integer newUsersToday = logMapper.queryNumRegisteredOrLogin(todayStr, "0102");
        analysisSummaryVo.setNewUsersToday(newUsersToday.longValue());
//        4.5  查询昨天的新增用户   select  count(DISTINCT user_id)  from tb_log  where log_time= '2021-01-18' and type='0102'
        Integer newUsersYesToday = logMapper.queryNumRegisteredOrLogin(before1Day, "0102");
//        5、今天新增用户的涨跌率  (今天数量-昨天的数量)/昨天的数量
        BigDecimal newUsersTodayRate = ComputeUtil.computeRate(newUsersToday, newUsersYesToday);
        analysisSummaryVo.setNewUsersTodayRate(newUsersTodayRate);

//        6、今日登陆人数  select  count(DISTINCT user_id)  from tb_log  where log_time= '2021-01-19' and type='0101'
        Integer loginTimesToday = logMapper.queryNumRegisteredOrLogin(todayStr, "0101");
        analysisSummaryVo.setLoginTimesToday(loginTimesToday.longValue());
//        6.5查询昨天的登陆用户   select  count(DISTINCT user_id)  from tb_log  where log_time= '2021-01-18' and type='0101'
        Integer loginTimesYesToday = logMapper.queryNumRegisteredOrLogin(before1Day, "0101");
//        7、登陆涨跌率   (今天数量-昨天的数量)/昨天的数量
        BigDecimal loginTimesTodayRate = ComputeUtil.computeRate(loginTimesToday, loginTimesYesToday);
        analysisSummaryVo.setLoginTimesTodayRate(loginTimesTodayRate);

//        8、活跃人数  select  count(DISTINCT user_id)  from tb_log  where log_time= '2021-01-19'
        Integer activeUsersToday = logMapper.queryNumActive(todayStr);
        analysisSummaryVo.setActiveUsersToday(activeUsersToday.longValue());
//        8.5查询昨天的活跃用户   select  count(DISTINCT user_id)  from tb_log  where log_time= '2021-01-18'
        Integer activeUsersYesToday = logMapper.queryNumActive(before1Day);
//        9、活跃涨跌率   (今天数量-昨天的数量)/昨天的数量
        BigDecimal activeUsersTodayRate = ComputeUtil.computeRate(activeUsersToday, activeUsersYesToday);
        analysisSummaryVo.setActiveUsersTodayRate(activeUsersTodayRate);

        return ResponseEntity.ok(analysisSummaryVo);

    }

    /**
     * //新增、活跃用户、次日留存率
     *
     * @param sd
     * @param ed
     * @param type
     * @return AnalysisUsersVo
     */
    public ResponseEntity users(Long sd, Long ed, Integer type) {
        AnalysisUsersVo vo = new AnalysisUsersVo();

        // 开始时间
        //long-->DateTime
        DateTime startDate = DateUtil.date(sd).setMutable(true);
        DateTime startDate2 = DateUtil.date(sd).setMutable(false);
        // 结束时间
        DateTime endDate = DateUtil.date(ed).setMutable(true);
        DateTime endDate2 = DateUtil.date(ed).setMutable(false);
        //偏移指定时间后（前）的时间
        DateTime lastStartDate = startDate2.offset(DateField.YEAR, -1).setMutable(true);
        DateTime lastEndDate = endDate2.offset(DateField.YEAR, -1).setMutable(true);
        // 今年
        vo.setThisYear(findDataPointVoList(startDate, endDate, type));
        // 去年
        vo.setLastYear(findDataPointVoList(lastStartDate, lastEndDate, type));

        return ResponseEntity.ok(vo);
    }

    /**
     * // 查询指定日期范围内的统计数据
     *
     * @param startDate
     * @param endDate
     * @param type
     * @return List<DataPointVo>
     */
    private List<DataPointVo> findDataPointVoList(DateTime startDate, DateTime endDate, Integer type) {
        List<DataPointVo> voList = new ArrayList<>();
        //获取开始到结束所有天数集合
        List<String> days = getDayList(startDate, endDate);
        //遍历每一天
        for (String day : days) {
            DataPointVo vo = new DataPointVo();

            vo.setTitle(day.split("-")[2]);

            //QueryWrapper<AnalysisByDay> queryWrapper = new QueryWrapper<>();
            //AnalysisByDay analysisByDay = analysisByDayMapper.selectOne(queryWrapper.select("distinct record_date").eq("record_date", day));


            if (type == 101) {
                Integer numRegistered = analysisByDayMapper.queryNumRegisteredOrLogin(day);
                //Integer numRegistered = analysisByDay.getNumRegistered();
                if (numRegistered != null) {
                    vo.setAmount(numRegistered.longValue());
                } else {
                    vo.setAmount(0L);
                }
            }

            if (type == 102) {
                Integer numActive = analysisByDayMapper.queryNumActive(day);
                //Integer numActive = analysisByDay.getNumActive();
                if (numActive != null) {
                    vo.setAmount(numActive.longValue());
                } else {
                    vo.setAmount(0L);
                }
            }
            if (type == 103) {
                Integer numRetention1d = analysisByDayMapper.queryNumRetention1d(day);
                //Integer numRetention1d = analysisByDay.getNumRetention1d();
                if (numRetention1d != null) {
                    vo.setAmount(numRetention1d.longValue());
                } else {
                    vo.setAmount(0L);
                }
            }
            voList.add(vo);
        }
        return voList;
    }

    /**
     * 开始到结束时间的日期集合
     *
     * @param startDate
     * @param endDate
     * @return List<String>
     */
    private List<String> getDayList(DateTime startDate, DateTime endDate) {
        // 返回的日期集合
        List<String> days = new ArrayList<String>();

        //endDate.offset(DateField.DAY_OF_YEAR,1);
        while (startDate.isBefore(endDate)) {
            days.add(startDate.toString().split(" ")[0]);
            startDate.offset(DateField.DAY_OF_YEAR, 1);
        }
        return days;
    }

    /**
     * 开始到结束时间的日期集合
     * @param startTime
     * @param endTime
     * @return List<String>
     */
   /*public static List<String> getDays(String startTime, String endTime) {

        // 返回的日期集合
        List<String> days = new ArrayList<String>();

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);

            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);

            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);

            //tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)

            //before()方法用于检查此日历时间是否早于给定Object的时间所表示的时间。
            while (tempStart.before(tempEnd)) {
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1);
                //tempEnd.add(Calendar.DAY_OF_YEAR, 1);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }

        return days;
    }*/
}
